<template>
  <div>
    <a-card>
      <p class="button_p">
        <a-button class="button_p_button" @click="saveDb">保存</a-button>
        <a-button class="button_p_button" @click="handlerRedo">恢复</a-button>
        <a-button class="button_p_button" @click="handlerUndo">撤销</a-button>
        <a-button class="button_p_button" @click="handlerZoom(0.1)">放大</a-button>
        <a-button class="button_p_button" @click="handlerZoom(-0.1)">缩小</a-button>
        <a-button class="button_p_button" @click="handlerZoom(1)">还原</a-button>
        <a-button class="button_p_button" @click="saveSvg">保存SVG</a-button>
        <a-button class="button_p_button" @click="saveXML">保存XML</a-button>
        <a-button class="button_p_button" @click="openFileInput">加载本地XML</a-button>
        <input type="file" id="files" style="display: none;margin-left: 10px" @change="loadXML"/>
      </p>
      <div class="containers">
        <div class="canvas" ref="canvas"></div>
        <div class="bpmn-js-properties-panel" id="js-properties-panel"></div>
      </div>
    </a-card>
  </div>
</template>

<script>
  import BpmnModeler from 'bpmn-js/lib/Modeler'
  import { XmlStr } from '@/mock/XmlStr'
  import customTranslate from '../../utils/act-chinese/customTranslate'
  import propertiesProviderModule from 'bpmn-js-properties-panel/lib/provider/camunda'
  import propertiesPanelModule from 'bpmn-js-properties-panel'
  import camundaModdleDescriptor from 'camunda-bpmn-moddle/resources/camunda'
  import { postAction, getAction } from '../../api/manage'

  export default {
    name: 'Modeler',
    data() {
      return {
        bpmnModeler: null,
        container: null,
        canvas: null,
        scale: 1,
        xmlStr: '',
        processModel: {},
        toDbModel: {},
        url: {
          //保存流程定义数据
          saveProcessDefinitionData: '/act/model/saveProcessDefinitionData',
          getProcessDefinitionData: '/act/model/getProcessDefinitionData'
        }
      }
    },
    // mounted() {
    //   // 生命周期钩子，在组件加载完成后调用init函数进行创建初始化Bpmn-js建模器
    //   this.init()
    // },
    watch: {
      processModel: 'processModelChange'
    },
    methods: {
      //初始化
      init() {
        const canvas = this.$refs.canvas
        // 将汉化包装成一个模块
        const customTranslateModule = {
          translate: ['value', customTranslate]
        }
        this.bpmnModeler = new BpmnModeler({
          container: canvas,
          keyboard: {
            bindTo: window
          },
          propertiesPanel: {
            parent: '#js-properties-panel'
          },
          additionalModules: [
            // 汉化模块
            customTranslateModule,
            propertiesProviderModule,
            propertiesPanelModule
          ],
          moddleExtensions: {
            camunda: camundaModdleDescriptor
          }
        })
        this.createNewDiagram()
      },
      //创建新的模型
      createNewDiagram() {
        try {
          const result = this.bpmnModeler.importXML(this.xmlStr)
          const { warnings } = result
          console.log(warnings)
        } catch (err) {
          console.log(err.message, err.warnings)
        }
      },
      //恢复
      handlerRedo() {
        this.bpmnModeler.get('commandStack').redo()
      },
      //撤销
      handlerUndo() {
        this.bpmnModeler.get('commandStack').undo()
      },
      //操作界面比例
      handlerZoom(radio) {
        const newScale = !radio ? 1.0 : this.scale + radio
        this.bpmnModeler.get('canvas').zoom(newScale)
        this.scale = newScale
      },
      //保存为xml
      async saveXML() {
        try {
          const result = await this.bpmnModeler.saveXML({ format: true })
          const { xml } = result

          var xmlBlob = new Blob([xml], {
            type: 'application/bpmn20-xml;charset=UTF-8,'
          })
          var downloadLink = document.createElement('a')
          downloadLink.download = 'ops-coffee-bpmn.bpmn'
          downloadLink.innerHTML = 'Get BPMN SVG'
          downloadLink.href = window.URL.createObjectURL(xmlBlob)
          downloadLink.onclick = function(event) {
            document.body.removeChild(event.target)
          }
          downloadLink.style.visibility = 'hidden'
          document.body.appendChild(downloadLink)
          downloadLink.click()
        } catch (err) {
          console.log(err)
        }
      },
      //保存为svg
      async saveSvg() {
        try {
          const result = await this.bpmnModeler.saveSVG()
          const { svg } = result

          var svgBlob = new Blob([svg], {
            type: 'image/svg+xml'
          })

          var downloadLink = document.createElement('a')
          downloadLink.download = 'ops-coffee-bpmn.svg'
          downloadLink.innerHTML = 'Get BPMN SVG'
          downloadLink.href = window.URL.createObjectURL(svgBlob)
          downloadLink.onclick = function(event) {
            document.body.removeChild(event.target)
          }
          downloadLink.style.visibility = 'hidden'
          document.body.appendChild(downloadLink)
          downloadLink.click()
        } catch (err) {
          console.log(err)
        }
      },
      //加载本地xml文件
      loadXML() {
        const that = this
        //获取input框
        let input = document.getElementById(`files`)
        //获取上传的本地文件
        let file = input.files[0]

        var reader = new FileReader()
        reader.readAsText(file)
        reader.onload = function() {
          that.xmlStr = this.result
          that.createNewDiagram()
        }
        //加载完成关闭input框
        input.style.display = 'none'
      },
      //打开input框
      openFileInput() {
        let files = document.getElementById('files')
        files.style.display = 'inline-block'
      },
      //保存模型定义数据到后台
      saveDb() {
        //获取bpmnStr
        this.bpmnModeler.saveXML({ format: true }).then(res => {
          this.toDbModel.bpmnStr = res.xml
        })
        //获取svgStr
        this.bpmnModeler.saveSVG().then(res => {
          this.toDbModel.svgStr = res.svg
        })
        this.toDbModel.modelId = this.processModel.id
        this.toDbModel.name = this.processModel.name
        this.toDbModel.key = this.processModel.key
        this.toDbModel.category = this.processModel.category
        //保存流程定义数据
        postAction(this.url.saveProcessDefinitionData, this.toDbModel).then(res => {
          if (res.success) {
            this.$message.success(res.message)
            this.$router.push({ path: '/activiti/manage' })
          } else {
            this.$message.error(res.message)
          }
        })
      },
      //加载模型定义数据
      loadXmlStr() {
        //调用后台接口，获取模型定义数据
        getAction(this.url.getProcessDefinitionData, { modelId: this.processModel.id }).then(res => {
          if (res.success) {
            if (res.result && res.result.modelEditorSource) {
              //如果从后台拿到模型定义数据，则直接使用后台数据
              this.xmlStr = res.result.modelEditorSource
            }
          }
          //判断是否加载到后台模型定义数据。
          if (!this.xmlStr) {
            //没有加载到数据则生成默认模版
            if (null != this.processModel && null != this.processModel.id) {
              this.xmlStr = XmlStr(this.processModel)
            }
          }
          //界面初始化
          this.init()
        })
      },
      //监听processModel改变
      processModelChange(val, oldVal) {
        this.loadXmlStr()
      }
    }
  }
</script>

<style lang="less" scoped>
  .containers {
    background: #9e9e9e;
    overflow: auto;
    background-image: linear-gradient(90deg,
    rgba(220, 220, 220, 0.5) 6%,
    transparent 0),
    linear-gradient(rgba(192, 192, 192, 0.5) 6%, transparent 0);
    background-size: 12px 12px;
    width: 100%;
    height: calc(100vh);
    -webkit-tap-highlight-color: rgba(255, 255, 255, 0);
  }

  .canvas {
    width: 100%;
    height: 100%;
  }

  .button_p {
    margin-bottom: 20px;

    .button_p_button {
      margin-left: 10px;
    }
  }

  .bpmn-js-properties-panel {
    position: absolute;
    top: 0;
    right: 0px;
    width: 300px;
    height: 100vh;
  }
</style>